package com.meiyuetao.myt.sale.entity;

import java.math.BigDecimal;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.EnumType;
import javax.persistence.Enumerated;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.Table;
import javax.persistence.Transient;
import javax.persistence.UniqueConstraint;

import lab.s2jh.core.annotation.MetaData;

import org.hibernate.annotations.Cache;
import org.hibernate.annotations.CacheConcurrencyStrategy;
import org.hibernate.envers.NotAudited;

import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.meiyuetao.myt.core.entity.MytBaseEntity;
import com.meiyuetao.myt.md.entity.Box;
import com.meiyuetao.myt.md.entity.Commodity;
import com.meiyuetao.myt.stock.entity.StorageLocation;

@MetaData(value = "销售订单行项下商品")
@Entity
@Table(name = "iyb_box_order_detail_commodity", uniqueConstraints = @UniqueConstraint(columnNames = { "ORDER_DETAIL_SID", "COMMODITY_SID", "IS_GIFT" }))
@Cache(usage = CacheConcurrencyStrategy.NONE)
public class BoxOrderDetailCommodity extends MytBaseEntity {
    private static final long serialVersionUID = 1L;
    @MetaData("关联订单")
    private BoxOrder boxOrder;
    @MetaData("关联订单行项")
    private BoxOrderDetail boxOrderDetail;
    @MetaData("商品")
    private Commodity commodity;
    @MetaData("数量")
    private BigDecimal quantity = BigDecimal.ZERO;
    @MetaData("价格")
    private BigDecimal price = BigDecimal.ZERO;
    @MetaData("调价后的价格")
    private BigDecimal modifiedPrice = BigDecimal.ZERO;
    @MetaData("盒子版本")
    private Integer boxVersion = 0;
    @MetaData("商品版本")
    private Integer commodityVersion = 0;
    @MetaData("成本价")
    private BigDecimal costPrice = BigDecimal.ZERO;
    @MetaData("状态")
    private CommentStatusEnum commentStatus = CommentStatusEnum.NO;
    @MetaData("关联盒子")
    private Box box;
    @MetaData(value = "库存地", comments = "用于销售库存锁定和释放，下订单时取商品commodity的defaultStorageLocation")
    private StorageLocation storageLocation;
    @MetaData(value = "销售锁定数量", comments = "对于立即可购买商品下单时，累加myt_stock_commodity的salingTotalQuantity属性后把对应锁定数量记录到此属性")
    private BigDecimal salingLockedQuantity = BigDecimal.ZERO;
    @MetaData(value = "已发货数量", comments = "关联创建销售单时追加更新此属性")
    private BigDecimal deliveriedQuantity = BigDecimal.ZERO;
    @MetaData(value = "原价金额", comments = "quantity*price")
    private BigDecimal originalAmount;
    @MetaData("折扣额")
    private BigDecimal discountAmount;
    @MetaData(value = "折后金额", comments = "算法：(BoxOrder.actualAmount-sum(所有运费))/sum(订单所有商品originalAmount)*originalAmount，为了保证由于小数精度导致的金额丢失，需要考虑把最后一笔以减法处理")
    private BigDecimal actualAmount = BigDecimal.ZERO;
    @MetaData("是否赠品")
    private Boolean gift = Boolean.FALSE;
    @MetaData(value = "已下达数量", comments = "关联创建销售单时追加更新此属性")
    private BigDecimal postedQuantity = BigDecimal.ZERO;
    @MetaData(value = "销售(成本)费用")
    private BigDecimal costAmount;
    @MetaData(value = "销售(运费)费用")
    private BigDecimal deliveryAmount;
    @MetaData(value = "商品金额")
    private BigDecimal commodityAmount;
    @MetaData("改价备注")
    private String modifierMemo;

    public enum CommentStatusEnum {

        @MetaData("NO")
        NO,

        @MetaData("YES")
        YES;
    }

    @ManyToOne
    @JoinColumn(name = "ORDER_DETAIL_SID", nullable = false)
    @JsonProperty
    public BoxOrderDetail getBoxOrderDetail() {
        return boxOrderDetail;
    }

    public void setBoxOrderDetail(BoxOrderDetail boxOrderDetail) {
        this.boxOrderDetail = boxOrderDetail;
    }

    @ManyToOne
    @JoinColumn(name = "ORDER_SID", nullable = false)
    @JsonProperty
    public BoxOrder getBoxOrder() {
        return boxOrder;
    }

    public void setBoxOrder(BoxOrder boxOrder) {
        this.boxOrder = boxOrder;
    }

    @ManyToOne
    @JoinColumn(name = "COMMODITY_SID", nullable = false)
    @JsonProperty
    public Commodity getCommodity() {
        return commodity;
    }

    public void setCommodity(Commodity commodity) {
        this.commodity = commodity;
    }

    @Column(nullable = false)
    public Integer getBoxVersion() {
        return boxVersion;
    }

    public void setBoxVersion(Integer boxVersion) {
        this.boxVersion = boxVersion;
    }

    @Column(nullable = false)
    public Integer getCommodityVersion() {
        return commodityVersion;
    }

    public void setCommodityVersion(Integer commodityVersion) {
        this.commodityVersion = commodityVersion;
    }

    @Column(precision = 18, scale = 2, nullable = false)
    @JsonProperty
    public BigDecimal getQuantity() {
        return quantity;
    }

    public void setQuantity(BigDecimal quantity) {
        this.quantity = quantity;
    }

    @Column(precision = 18, scale = 2, nullable = true)
    @JsonProperty
    public BigDecimal getPrice() {
        return price;
    }

    public void setPrice(BigDecimal price) {
        this.price = price;
    }

    @Column(precision = 18, scale = 2)
    public BigDecimal getCostPrice() {
        return costPrice;
    }

    public void setCostPrice(BigDecimal costPrice) {
        this.costPrice = costPrice;
    }

    @Column(precision = 18, scale = 2)
    @JsonProperty
    public BigDecimal getModifiedPrice() {
        return modifiedPrice;
    }

    public void setModifiedPrice(BigDecimal modifiedPrice) {
        this.modifiedPrice = modifiedPrice;
    }

    @Transient
    @JsonProperty
    public BigDecimal getFinalPrice() {
        return modifiedPrice != null ? modifiedPrice : price;
    }

    @Enumerated(EnumType.STRING)
    @Column(length = 8)
    @JsonProperty
    public CommentStatusEnum getCommentStatus() {
        return commentStatus;
    }

    public void setCommentStatus(CommentStatusEnum commentStatus) {
        this.commentStatus = commentStatus;
    }

    @ManyToOne
    @JoinColumn(name = "BOX_SID", nullable = false)
    @NotAudited
    public Box getBox() {
        return box;
    }

    public void setBox(Box box) {
        this.box = box;
    }

    @ManyToOne
    @JoinColumn(name = "storage_location_sid")
    @NotAudited
    @JsonProperty
    public StorageLocation getStorageLocation() {
        return storageLocation;
    }

    public void setStorageLocation(StorageLocation storageLocation) {
        this.storageLocation = storageLocation;
    }

    @Column(precision = 18, scale = 2)
    @JsonProperty
    public BigDecimal getDeliveriedQuantity() {
        return deliveriedQuantity;
    }

    public void setDeliveriedQuantity(BigDecimal deliveriedQuantity) {
        this.deliveriedQuantity = deliveriedQuantity;
    }

    @JsonProperty
    @Transient
    public BigDecimal getToDeliveryQuantity() {
        return deliveriedQuantity == null ? quantity : quantity.subtract(deliveriedQuantity);
    }

    @JsonProperty
    @Column(name = "is_gift")
    public Boolean getGift() {
        return gift;
    }

    public void setGift(Boolean gift) {
        this.gift = gift;
    }

    @Column(precision = 18, scale = 2)
    @JsonProperty
    public BigDecimal getOriginalAmount() {
        return originalAmount;
    }

    public void setOriginalAmount(BigDecimal originalAmount) {
        this.originalAmount = originalAmount;
    }

    @JsonProperty
    public BigDecimal getSalingLockedQuantity() {
        return salingLockedQuantity;
    }

    public void setSalingLockedQuantity(BigDecimal salingLockedQuantity) {
        this.salingLockedQuantity = salingLockedQuantity;
    }

    @JsonProperty
    public BigDecimal getPostedQuantity() {
        return postedQuantity;
    }

    public void setPostedQuantity(BigDecimal postedQuantity) {
        this.postedQuantity = postedQuantity;
    }

    @JsonProperty
    public BigDecimal getDiscountAmount() {
        return discountAmount;
    }

    public void setDiscountAmount(BigDecimal discountAmount) {
        this.discountAmount = discountAmount;
    }

    @JsonProperty
    @Column(name = "amount")
    public BigDecimal getActualAmount() {
        return actualAmount;
    }

    public void setActualAmount(BigDecimal actualAmount) {
        this.actualAmount = actualAmount;
    }

    @JsonProperty
    public BigDecimal getCostAmount() {
        return costAmount;
    }

    public void setCostAmount(BigDecimal costAmount) {
        this.costAmount = costAmount;
    }

    @JsonProperty
    public BigDecimal getDeliveryAmount() {
        return deliveryAmount;
    }

    public void setDeliveryAmount(BigDecimal deliveryAmount) {
        this.deliveryAmount = deliveryAmount;
    }

    @JsonProperty
    public BigDecimal getCommodityAmount() {
        return commodityAmount;
    }

    public void setCommodityAmount(BigDecimal commodityAmount) {
        this.commodityAmount = commodityAmount;
    }

    @Transient
    @JsonIgnore
    public String getSubVoucher() {
        return commodity.getSku();
    }

    @Column(length = 2000)
    @JsonProperty
    public String getModifierMemo() {
        return modifierMemo;
    }

    public void setModifierMemo(String modifierMemo) {
        this.modifierMemo = modifierMemo;
    }

}
